package com.parking.mgr.common.exception.asserts;

import com.parking.mgr.common.exception.BaseException;
import com.parking.mgr.common.exception.ServiceException;
import com.parking.mgr.common.pojo.response.Result;
import org.apache.commons.lang3.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @ClassName Assertion
 * @Description 断言接口
 * @Auther: zhijianpu
 * @Date: 2023/5/18
 */
public interface Assertion {

    /**
     * 断言判定不通过时，抛出的异常
     * @return 断言判定不通过时，抛出的异常
     */
    default BaseException onAssertFailed(String errorMessage){
        return new ServiceException(Result.DEFAULT_ERROR_CODE,
                StringUtils.isEmpty(errorMessage) ? Result.DEFAULT_ERROR_MESSAGE : errorMessage);
    }

    /**
     * 判定表达式为TRUE, 否则抛出异常
     * @param expression 待考察的表达式
     */
    default void assertTrue(boolean expression) {
        assertTrue(expression, null);
    }

    /**
     * 判定表达式为TRUE, 否则抛出异常
     * @param expression 待考察的表达式
     */
    default void assertTrue(boolean expression, String errorMessage) {
        if (!expression) {
            throw onAssertFailed(errorMessage);
        }
    }

    /**
     * 判定表达式为TRUE, 否则抛出异常
     * @param expressions 待考察的表达式
     */
    default void assertAllTrue(List<Boolean> expressions) {
        expressions.forEach(this::assertTrue);
    }


    /**
     * 判定对象为 null，否则抛出异常
     * @param obj 待考察的对象
     */
    default void assertNull(Object obj) {
        assertTrue(null == obj);
    }

    /**
     * 判定对象为 null，否则抛出异常
     * @param obj 待考察的对象
     */
    default void assertNull(Object obj, String errorMessage) {
        assertTrue(null == obj, errorMessage);
    }


    /**
     * 判定对象不为 null，否则抛出异常
     * @param obj 待考察的对象
     */
    default void assertNotNull(Object obj) {
        assertTrue(null != obj);
    }

    /**
     * 判定对象不为 null，否则抛出异常
     * @param obj 待考察的对象
     */
    default void assertNotNull(Object obj, String errorMessage) {
        assertTrue(null != obj, errorMessage);
    }

    /**
     * 判定对象不为空（不为null，不为空字符，不为空白字符，不为空集合, 不为空map, 不为空数组, 数组里的元素不全为空,  optional 不为空），否则抛出异常
     * @param obj 待考察的对象
     */
    default void assertNotEmpty(Object obj) {
        assertNotEmpty(obj, null);
    }

    /**
     * 判定对象不为空（不为null，不为空字符，不为空白字符，不为空集合, 不为空map, 不为空数组, 数组里的元素不全为空, optional 不为空），否则抛出异常
     * @param obj 待考察的对象
     */
    default void assertNotEmpty(Object obj, String errorMessage) {
        assertNotNull(obj, errorMessage);

        if(obj instanceof Optional<?> opt) {
            assertTrue(opt.isPresent());
        } else if (obj instanceof CharSequence cs){
            assertTrue(cs.length() > 0, errorMessage);
        } else if (obj instanceof Collection<?> collection){
            assertTrue(!collection.isEmpty(), errorMessage);
        } else if (obj instanceof Map<?,?> map) {
            assertTrue(!map.isEmpty(), errorMessage);
        } else if (obj instanceof Object[] array) {
            assertTrue(array.length > 0, errorMessage);
            boolean allEmpty = true;
            for (Object o : array) {
                try {
                    assertNotEmpty(o);
                    allEmpty = false;
                } catch (Exception ignored) {
                }
            }
            if (allEmpty) {
                throw onAssertFailed(errorMessage);
            }
        }
    }

    /**
     * 判定对象 不为 空白字符，不为 null，否则抛出异常
     * @param obj 待考察的对象
     */
    default void assertNotBlank(String obj) {
        assertNotBlank(obj, null);
    }

    /**
     * 判定对象 不为 空白字符，不为 null，否则抛出异常
     * @param obj 待考察的对象
     */
    default void assertNotBlank(String obj, String errorMessage) {
        assertNotNull(obj, errorMessage);
        assertTrue(!obj.isBlank(), errorMessage);
    }
}
